package com.smartwebx.ha.biz.rainwater.real.impl;

import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.google.common.base.Objects;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.smartwebx.ha.biz.assign.HaStationGroupCfgManager;
import com.smartwebx.ha.biz.rainwater.real.LayerRainfallManager;
import com.smartwebx.ha.biz.rainwater.real.RainfallManager;
import com.smartwebx.ha.dal.assign.bean.HaArea;
import com.smartwebx.ha.dal.assign.dao.HaRainWaterStatGrpMapper;
import com.smartwebx.ha.dal.feature.dao.FeatureRainfallMapper;
import com.smartwebx.ha.dal.realtime.dao.RainfallMapper;
import com.smartwebx.ha.dal.realtime.dao.StatGroupMapper;
import com.smartwebx.ha.dal.realtime.prod.ProductMapper;
import com.smartwebx.ha.dal.usebean.DateValue;
import com.smartwebx.ha.dal.usebean.FeatureRainfallYear;
import com.smartwebx.ha.dal.usebean.RainSlideDay;
import com.smartwebx.ha.dal.usebean.RainSlideHour;
import com.smartwebx.ha.dal.usebean.SimpleStatGroup;
import com.smartwebx.ha.dal.usebean.SimpleStatGroup2;
import com.smartwebx.ha.dal.usebean.SplitDatePointBean;
import com.smartwebx.ha.dal.usebean.StatDateValue;
import com.smartwebx.ha.dal.usebean.StationValue;
import com.smartwebx.ha.dal.usebean.SuperStatGroup;
import com.smartwebx.ha.dal.usebean.SuperStatGroup2;
import com.smartwebx.ha.dal.util.DateFullProcess;
import com.smartwebx.ha.dal.util.DateValueHandler;
import com.smartwebx.ha.dal.util.SplitDatePoint;
import com.smartwebx.ha.dal.util.core.RainSlideAnalysis;
import com.smartwebx.ha.util.ReadINI;

@Service
public class LayerRainfallManagerImpl implements LayerRainfallManager {
	@Autowired
	private RainfallManager rainfallService;
	@Autowired
	private RainfallMapper rainfallDao;
	@Autowired
	private StatGroupMapper statGroupDao;
	@Autowired
	private FeatureRainfallMapper featureRainfallDao;
	@Autowired
	private HaStationGroupCfgManager haStationGroupCfgService;
	@Autowired
	private HaRainWaterStatGrpMapper haRainWaterStatGrp;
	@Autowired
	private ProductMapper productDao;

	@Override
	public RainSlideDay getRainSlideDay(String stcd, List<DateValue> process) {
		List<FeatureRainfallYear> featureRainfallYears = featureRainfallDao
				.getRainSlideDay(stcd);
		return RainSlideAnalysis.getSlideAnalysisDay(featureRainfallYears,
				process);
	}

	@Override
	public RainSlideHour getRainSlideHour(String stcd, List<DateValue> process) {
		List<FeatureRainfallYear> featureRainfallYears = featureRainfallDao
				.getRainSlideDay(stcd);

		return RainSlideAnalysis.getSlideAnalysisHour(featureRainfallYears,
				process);
	}

	@Override
	public List<SuperStatGroup> getLayerRainfall(HaArea area,
			Map<String, Double> statValMap) {
		List<SuperStatGroup> superSimpleStatGs = haStationGroupCfgService
				.getSuperStatGroupByAreaId(area.getId());
		ReadINI readINI = new ReadINI();
		Map<String, String> map = readINI.getValue("区域属性", "计算面平均",
				"D://VisoLine//work//VisoLine.ini");
		if (area.getCode().equals("320000")) {
			for (SuperStatGroup superSimple : superSimpleStatGs) {
				for (SimpleStatGroup simpleStatG : superSimple
						.getSimpleStatGList()) {
					String string = map.get(simpleStatG.getAstnm());

					if (string == null || "".equals(string)) {
						simpleStatG.setValue(0.0);
					} else {
						simpleStatG.setValue(Double.parseDouble(string));
					}
				}
			}
		} else {
			for (SuperStatGroup superSimple : superSimpleStatGs) {
				for (SimpleStatGroup simpleStatG : superSimple
						.getSimpleStatGList()) {
					List<String> stcds = simpleStatG.getStcds();
					Double avgValue = Double.valueOf(0.0D);
					Double sumValue = Double.valueOf(0.0D);
					for (String stcd : stcds) {
						sumValue = Double.valueOf(sumValue.doubleValue()
								+ ((Double) Objects.firstNonNull(
										statValMap.get(stcd),
										Double.valueOf(0.0D))).doubleValue());
					}
					avgValue = Double.valueOf(sumValue.doubleValue()
							/ stcds.size());
					simpleStatG.setValue(avgValue);
				}
			}
		}

		return superSimpleStatGs;
	}

	/**
	 * 根据面雨量类型获得站群分类
	 * 
	 * @param purposeTypeName
	 *            面雨量类型（雨量100、雨量150、水资源分区雨量码） 默认 雨量100
	 * @return
	 */
	/**
	 * private List<SuperStatGroup> getStatGroup(final String purposeTypeName) {
	 * List<StatGroup> statGroups = statGroupDao.getAllStatGroupStcdFilter();
	 * List<SuperStatGroup> superSimpleStatGs = Lists.newArrayList(); Boolean
	 * inWeb = StatGroupThreadLocal.getInWeb(); Set<String> useStatGroups =
	 * StatGroupThreadLocal.getStatGroups();
	 * 
	 * // 根据面雨量类型过滤匹配的站码 Iterable<StatGroup> filterStatGroups =
	 * Iterables.filter(statGroups, new Predicate<StatGroup>() {
	 * 
	 * @Override public boolean apply(StatGroup input) { return
	 *           Objects.equal(purposeTypeName, input.getPurpose()); } }); //
	 *           根据行政分区字段得到分区下的站群码 ImmutableListMultimap<String, StatGroup>
	 *           filterStatGroupMultiMaps = Multimaps .index(filterStatGroups,
	 *           new Function<StatGroup, String>() {
	 * @Override public String apply(StatGroup input) { return input.getAtype();
	 *           } }); for (String atype : filterStatGroupMultiMaps.keySet()) {
	 *           String preAstcd = null;
	 * 
	 *           SuperStatGroup superStatGroup = new SuperStatGroup();
	 * 
	 *           // 根据行政分区得到的站群组 ImmutableList<StatGroup> atypeStatGroups =
	 *           filterStatGroupMultiMaps .get(atype);
	 *           superStatGroup.setAtype(atype);
	 * 
	 *           SimpleStatGroup simpleStatGroup = new SimpleStatGroup();
	 *           Set<String> allowStcds = Sets.newHashSet(); for (StatGroup sg :
	 *           atypeStatGroups) { if (preAstcd != null &&
	 *           !Objects.equal(sg.getAstcd(), preAstcd)) { simpleStatGroup =
	 *           new SimpleStatGroup(); if (inWeb) { // 过滤后的站码 SetView<String>
	 *           filterStatGroup = Sets.intersection( allowStcds,
	 *           useStatGroups);
	 * 
	 *           if (!filterStatGroup.isEmpty()) {
	 *           simpleStatGroup.setStcds(filterStatGroup);
	 *           superStatGroup.setSimpleStatGList(simpleStatGroup); } } else {
	 *           simpleStatGroup.setStcds(allowStcds);
	 *           superStatGroup.setSimpleStatGList(simpleStatGroup); }
	 *           allowStcds.clear(); } preAstcd = sg.getAstcd();
	 * 
	 *           simpleStatGroup.setAstcd(preAstcd);
	 *           simpleStatGroup.setAstnm(sg.getAstnm());
	 *           simpleStatGroup.setOrd(sg.getOrd());
	 *           allowStcds.add(sg.getStcd()); }
	 * 
	 *           if (!superStatGroup.getSimpleStatGList().isEmpty()) {
	 *           superSimpleStatGs.add(superStatGroup); } }
	 * 
	 *           return superSimpleStatGs; }
	 **/

	@Override
	public List<DateValue> getDayLayerRainfall(String statGroupCode,
			Date startDate, Date endDate) {
		List<DateValue> rainfallPro = Lists.newArrayList();

		List<String> stcds = haRainWaterStatGrp
				.getRainWaterStationByStatGroupId(statGroupCode);
		SplitDatePointBean splitDPBean = SplitDatePoint.splitDatePoint(
				startDate, endDate);

		String operatType = splitDPBean.getOperatType();
		Date startTime = splitDPBean.getStartDate();
		Date endTime = splitDPBean.getEndDate();
		Date startHour = splitDPBean.getStartHour();
		Date endHour = splitDPBean.getEndHour();
		Date startNextTime = null;
		Date endNextTime = null;

		Set<Date> dateProcess = Sets.newHashSet();

		Date nowDate = DateUtils.truncate(new Date(), Calendar.DATE);
		List<StatDateValue> statDateVals = null;
		if ("127".indexOf(operatType) <= -1) {
			startNextTime = DateUtils.addDays(startTime, 1);
			endNextTime = DateUtils.addDays(endTime, 1);
		}

		if ("127".indexOf(operatType) > -1) {
			// 小时雨量总值
			List<StationValue> statHourRainVal = rainfallDao
					.getMoreStatHourTotalRainValInQuery(stcds, startHour,
							endHour);
			if (Objects.equal("2", operatType)) {
				nowDate = DateUtils.addDays(nowDate, -1);
			}
			List<StatDateValue> nowStatDateVal = Lists.newArrayList();
			for (StationValue sv : statHourRainVal) {
				StatDateValue sdv = new StatDateValue();
				sdv.setTm(nowDate);
				sdv.setVal(sv.getVal());
				sdv.setStcd(sv.getStcd());
				nowStatDateVal.add(sdv);
			}
			statDateVals = nowStatDateVal;

			dateProcess.add(nowDate);
		} else if (Objects.equal(operatType, "3")) {
			// 单日日雨量值 下一日8时雨量值
			statDateVals = rainfallDao.getMoreStatOneDayRainValInQuery(stcds,
					startNextTime);

			dateProcess.add(startTime);
		} else if ("45".indexOf(operatType) > -1) {
			// 多日日雨量与当日各小时段雨量
			if (Objects.equal("5", operatType)) { // 不到8时，日期不向下移
				statDateVals = rainfallDao.getMoreStatMoreDayRainValInQuery(
						stcds, startNextTime, endTime);
			} else if (Objects.equal("4", operatType)) {// 超过8时，日期下移一天
				statDateVals = rainfallDao.getMoreStatMoreDayRainValInQuery(
						stcds, startNextTime, endNextTime);
			}
			// 日期过程
			dateProcess = DateFullProcess.returnDateSectStr(startTime,
					endNextTime).keySet();

			// 当日雨量
			List<StationValue> moreStatRainVal = rainfallDao
					.getMoreStatHourTotalRainValInQuery(stcds, startHour,
							endHour);
			if (Objects.equal("5", operatType)) {
				nowDate = DateUtils.addDays(nowDate, -1);
			}
			List<StatDateValue> nowStatDateVal = Lists.newArrayList();
			for (StationValue sv : moreStatRainVal) {
				StatDateValue sdv = new StatDateValue();
				sdv.setTm(nowDate);
				sdv.setVal(sv.getVal());
				sdv.setStcd(sv.getStcd());
				nowStatDateVal.add(sdv);
			}

			// 合并 List
			statDateVals.addAll(nowStatDateVal);
		} else if (Objects.equal("6", operatType)) {
			// 多日雨量过程
			statDateVals = rainfallDao.getMoreStatMoreDayRainValInQuery(stcds,
					startNextTime, endNextTime);
			// 日期过程
			dateProcess = DateFullProcess.returnDateSectStr(startTime, endTime)
					.keySet();
		}

		for (final Date date : dateProcess) {
			DateValue dv = new DateValue();
			dv.setTm(date);
			Iterable<StatDateValue> findStatDateVals = Iterables.filter(
					statDateVals, new Predicate<StatDateValue>() {
						@Override
						public boolean apply(StatDateValue input) {
							Date nowTm = input.getTm();
							nowTm = DateUtils.truncate(nowTm, Calendar.DATE);
							nowTm = DateUtils.addDays(nowTm, -1);
							return Objects.equal(nowTm, date);
						}
					});
			Double val = DateValueHandler.avgByObj(findStatDateVals,
					stcds.size());
			dv.setVal(val);

			rainfallPro.add(dv);
		}

		return rainfallPro;
	}

	@Override
	public List<DateValue> getHourLayerRainfall(String statGroupCode,
			Date startH, Date endH) {
		// List<String> stcds = statGroupDao.getStcdsByAstcdStcdFilter(astcd);
		List<String> stcds = haRainWaterStatGrp
				.getRainWaterStationByStatGroupId(statGroupCode);
		SplitDatePointBean splitDPBean = SplitDatePoint.splitDatePoint(startH,
				endH);

		String operatType = splitDPBean.getOperatType();
		Date startTime = splitDPBean.getStartDate();
		Date endTime = splitDPBean.getEndDate();
		Date startHour = splitDPBean.getStartHour();
		Date endHour = splitDPBean.getEndHour();

		Date startHPoint = null;
		Date endHPoint = null;

		if ("127".indexOf(operatType) > -1) {
			startHPoint = startHour;
			endHPoint = endHour;
		} else if ("36".indexOf(operatType) > -1) {
			startHPoint = DateUtils.addHours(startTime, 9);
			endHPoint = endTime;

			// 加一天 加 8小时
			endHPoint = DateUtils.addHours(DateUtils.addDays(endHPoint, 1), 8);
		} else if ("45".indexOf(operatType) > -1) {
			startHPoint = DateUtils.addHours(startTime, 9);
			endHPoint = endHour;
		}

		List<StatDateValue> moreStatHourRainVal = rainfallDao
				.getMoreStatHourRainValInQuery(stcds, startHPoint, endHPoint);
		Set<Date> hourProcess = DateFullProcess.returnTimeSectStr(startHPoint,
				endHPoint).keySet();
		List<DateValue> rainfallProcess = Lists.newArrayList();
		for (final Date date : hourProcess) {
			DateValue dv = new DateValue();
			dv.setTm(date);
			Iterable<StatDateValue> findStatDateVals = Iterables.filter(
					moreStatHourRainVal, new Predicate<StatDateValue>() {
						@Override
						public boolean apply(StatDateValue input) {
							Date nowTm = input.getTm();
							nowTm = DateUtils.truncate(nowTm,
									Calendar.HOUR_OF_DAY);
							return Objects.equal(nowTm, date);
						}
					});
			Double val = DateValueHandler.avgByObj(findStatDateVals,
					stcds.size());
			dv.setVal(val);

			rainfallProcess.add(dv);
		}

		return rainfallProcess;
	}

	@Override
	@SuppressWarnings("unchecked")
	public List<SuperStatGroup2> getSimpleStatGroup(String astcd,
			String startDate, String endDate) {
		Map<String, Object> map = Maps.newHashMap();
		map.put("areaStcd", astcd);
		map.put("startTm", startDate);
		map.put("endTm", endDate);
		productDao.findTimeLayerRain(map);

		List<SimpleStatGroup2> simpleStatGroup = (List<SimpleStatGroup2>) map
				.get("result");
		Collections.sort(simpleStatGroup, new Comparator<SimpleStatGroup2>() {
			@Override
			public int compare(SimpleStatGroup2 o1, SimpleStatGroup2 o2) {
				String astcd1 = o1.getAstcd();
				String astcd2 = o2.getAstcd();
				return astcd1.compareTo(astcd2);
			}
		});

		// 行政分区
		List<SuperStatGroup2> superStatGroup2s = Lists.newArrayList();
		SuperStatGroup2 superStatGroup = new SuperStatGroup2();
		superStatGroup.setAtype("行政分区");
		superStatGroup.setSimpleStatGList(simpleStatGroup);
		superStatGroup.setAcode("xingzheng");
		superStatGroup2s.add(superStatGroup);

		// 流域
		List<SimpleStatGroup2> liuyuLayerRainData = this.getLayerRainData2("流域", startDate, endDate);
		superStatGroup = new SuperStatGroup2();
		superStatGroup.setAtype("流域分区");
		superStatGroup.setSimpleStatGList(liuyuLayerRainData);
		superStatGroup.setAcode("liuyu");
		superStatGroup2s.add(superStatGroup);
		// 地理
		List<SimpleStatGroup2> diliLayerRainData = this.getLayerRainData2("地理", startDate, endDate);
		superStatGroup = new SuperStatGroup2();
		superStatGroup.setAtype("地理分区");
		superStatGroup.setSimpleStatGList(diliLayerRainData);
		superStatGroup.setAcode("dili");
		superStatGroup2s.add(superStatGroup);
		// 水资源
		List<SimpleStatGroup2> waterResourceLayerRainData = this.getLayerRainData2("水资源", startDate, endDate);
		superStatGroup = new SuperStatGroup2();
		superStatGroup.setAtype("水资源分区");
		superStatGroup.setSimpleStatGList(waterResourceLayerRainData);
		superStatGroup.setAcode("shuiziyuan");
		superStatGroup2s.add(superStatGroup);
		

		return superStatGroup2s;
	}

	@SuppressWarnings("unchecked")
	private List<SimpleStatGroup2> getLayerRainData2(String areaName,
			String startDate, String endDate) {
		
		Map<String, Object> map = Maps.newHashMap();
		map.put("areaStcd", areaName);
		map.put("startTm", startDate);
		map.put("endTm", endDate);
		productDao.findTimeLayerRain2(map);

		List<SimpleStatGroup2> simpleStatGroup = (List<SimpleStatGroup2>) map
				.get("result");
		
		return simpleStatGroup;
	}

	@Override
	public List<DateValue> getDayLayerRainfall2(String astcd, Date startDate,
			Date endDate) {
		return getLayerRainfall(astcd, startDate, endDate, "1");
	}

	@Override
	public List<DateValue> getHourLayerRainfall2(String astcd, Date startHour,
			Date endHour) {
		return getLayerRainfall(astcd, startHour, endHour, "2");
	}

	private List<DateValue> getLayerRainfall(String stcd, Date startDate,
			Date endDate, String type) {
		String startStr = DateFormatUtils.format(startDate, "yyyy-MM-dd");
		String endStr = DateFormatUtils.format(endDate, "yyyy-MM-dd");

		Set<Date> dayProcess = null;
		if ("1".equals(type)) {
			dayProcess = DateFullProcess.returnDateSectStr(startDate, endDate)
					.keySet();
		} else if ("2".equals(type)) {
			dayProcess = DateFullProcess.returnTimeSectStr(startDate, endDate)
					.keySet();
		}
		Map<String, Object> result = Maps.newHashMap();
		result.put("areaStcd", stcd);
		result.put("startTm", startStr);
		result.put("endTm", endStr);
		result.put("type", type);

		productDao.findTimeLayerRainProccess(result);

		List<SimpleStatGroup2> simpleStatGroups = (List<SimpleStatGroup2>) result
				.get("result");
		List<DateValue> dvs = Lists.newArrayList();
		for (int i = 0; i < simpleStatGroups.size(); i++) {
			SimpleStatGroup2 simpleStatGroup = simpleStatGroups.get(i);
			Date day = Iterables.get(dayProcess, i);
			dvs.add(new DateValue(day, simpleStatGroup.getValue()));
		}
		return dvs;
	}
}
